home *** CD-ROM | disk | FTP | other *** search
- ;; PC Scheme Common Lisp Compatibility Package
- ;;
- ;; (c) Copyright 1990 Carl W. Hoffman. All rights reserved.
- ;;
- ;; This file may be freely copied, distributed, or modified for non-commercial
- ;; use provided that this copyright notice is not removed. For further
- ;; information about other utilities for Common Lisp or Scheme, contact the
- ;; following address:
- ;;
- ;; Carl W. Hoffman, 363 Marlborough Street, Boston, MA 02115, U.S.A.
- ;; Internet: CWH@AI.MIT.EDU CompuServe: 76416,3365 Fax: 617-262-4284
-
- ;; This package has been tested with PC Scheme version 3.02.
-
- ;; To do:
- ;; Place all of these bindings in a separate environment so
- ;; as not to break Scheme programs. The property lists
- ;; will still be broken, however.
- ;; N-ary =, /=, <, >, <=, >=, CHAR=, CHAR/=, CHAR<, CHAR>, CHAR<=, CHAR>=
- ;; Translate T into ELSE inside of COND.
- ;; Implement DO*, PROG*
- ;; Create DEFUN-CL, DEFMACRO-CL, and DEFUN-INLINE-CL for creating
- ;; user-visible CL functions and macros. This should create an arglist,
- ;; like DEFUN. Hide internal functions in a CL-INTERNALS environment
- ;; which isn't user-visible.
- ;; Implement ECASE correctly.
-
- ;; R^3RS functions missing from PC Scheme. See also the file R3RS.SCM.
-
- ;************************************************************************
- ; added by LB, because suppressed in PCS.
- (define-integrable nil '())
- (define-integrable t #T)
- ;************************************************************************
-
- (define (char-upper-case? char)
- (and (char<=? #\A char) (char<=? char #\Z)))
-
- (define (char-lower-case? char)
- (and (char<=? #\a char) (char<=? char #\z)))
-
- (define (char-alphabetic? char)
- (or (char-upper-case? char)
- (char-lower-case? char)))
-
- (define (char-numeric? char)
- (and (char<=? #\0 char) (char<=? char #\9)))
-
- (define (char-whitespace? char)
- (or (char=? char #\space)
- (char=? char #\tab)
- (char=? char #\newline)))
-
- ;; Use DEFINE-INTEGRABLE rather than ALIAS, SYNTAX, or MACRO when defining
- ;; function synonyms. If ALIAS, SYNTAX, or MACRO is used, then it is not
- ;; possible to later use that name as a local variable.
-
- (define-integrable null null?)
- (define-integrable atom atom?)
- (define-integrable consp pair?)
- (define-integrable symbolp symbol?)
- (define-integrable simple-string-p string?)
- (define-integrable simple-vector-p vector?)
- (define-integrable stringp string?)
- (define-integrable vectorp vector?)
- (define-integrable numberp number?)
- (define-integrable integerp integer?)
- (define-integrable rationalp rational?)
- (define-integrable floatp float?)
- (define-integrable characterp char?)
-
- (defun-inline listp (x)
- (or (null x) (pair? x)))
-
- (defun-clcp %%endp-error (x)
- (error "The argument to ENDP, ~S, was not a list." x))
-
- (defun-inline endp (x)
- (or (null x)
- (and (not (pair? x))
- (%%endp-error x))))
-
- (define-integrable eq eq?)
- (define-integrable eql eqv?)
- (define-integrable equal equal?)
-
- (define-integrable zerop zero?)
- (define-integrable plusp positive?)
- (define-integrable minusp negative?)
- (define-integrable oddp odd?)
- (define-integrable evenp even?)
-
- (defun-inline /= (n1 n2)
- (not (= n1 n2)))
-
- (define-integrable char= char=?)
- (define-integrable char< char<?)
- (define-integrable char> char>?)
- (define-integrable char<= char<=?)
- (define-integrable char>= char>=?)
-
- (defun-inline char/= (c1 c2)
- (not (char= c1 c2)))
-
- (define-integrable char-equal char-ci=?)
- (define-integrable char-lessp char-ci<?)
- (define-integrable char-greaterp char-ci>?)
- (define-integrable char-not-lessp char-ci>=?)
- (define-integrable char-not-greaterp char-ci<=?)
-
- ;; The following functions are all integrable. The translator should have a
- ;; flag to enable integration and disable type checking.
-
- (defun-inline char-not-equal (c1 c2)
- (not (char-equal c1 c2)))
-
- (defun standard-char-p (char)
- (check-type char character)
- t)
-
- (defun graphic-char-p (char)
- (check-type char character)
- (not (or (char= char #\newline)
- (char= char #\tab)
- (char= char #\page))))
-
- (defun string-char-p (char)
- (check-type char character)
- t)
-
- (defun alpha-char-p (char)
- (check-type char character)
- (char-alphabetic? char))
-
- (defun upper-case-p (char)
- (check-type char character)
- (char-upper-case? char))
-
- (defun lower-case-p (char)
- (check-type char character)
- (char-lower-case? char))
-
- (defun both-case-p (char)
- (check-type char character)
- (char-alphabetic? char))
-
- (defun digit-char-p (char)
- (check-type char character)
- (and (char-numeric? char)
- (- (char-code char) (char-code #\0))))
-
- (defun alphanumericp (char)
- (check-type char character)
- (or (char-alphabetic? char) (char-numeric? char)))
-
- (define-integrable last last-pair)
-
- (define-integrable 1- -1+)
-
- (define-integrable intern string->symbol)
- (define-integrable get getprop)
-
- (define-integrable symbol-name symbol->string)
- (define-integrable symbol-plist proplist)
-
- (defmacro defvar (name &optional (initial-value nil iv?) documentation)
- (when (and documentation (not (stringp documentation)))
- (error "The third argument to DEFVAR was ~S, which is not a ~
- documentation string."
- documentation))
- `(begin
- (if (eq #!unassigned (access ,name (the-environment)))
- (define ,name . ,(if iv? `(,initial-value) '())))
- ',name))
-
- (defmacro defparameter (name initial-value &optional documentation)
- (when (and documentation (not (stringp documentation)))
- (error "The third argument to DEFPARAMETER was ~S, which is not a ~
- documentation string."
- documentation))
- `(begin
- (define ,name ,initial-value)
- ',name))
-
- (defmacro defconstant (name initial-value &optional documentation)
- (when (and documentation (not (stringp documentation)))
- (error "The third argument to DEFPARAMETER was ~S, which is not a ~
- documentation string."
- documentation))
- `(begin
- (define-integrable ,name ,initial-value)
- ',name))
-
- (alias prog1 begin0)
- (alias progn begin)
-
- (defmacro prog2 (first second &rest rest)
- `(begin ,first ,(if rest `(begin0 ,second . ,rest) second)))
-
- (syntax (declare . declarations) 'declare)
- (syntax (proclaim . declarations) 'proclaim)
-
- (syntax (when condition . body)
- (cond (condition . body)))
-
- (syntax (unless condition . body)
- (cond ((not condition) . body)))
-
- (defmacro values (&rest args)
- (if (null args)
- '*the-non-printing-object*
- (car args)))
-
- ;; This should use CHECK-ARG-TYPE or whatever the CL thing is.
-
- (defun-clcp macro-function (symbol &optional (error? t))
- (if (symbolp symbol)
- (get symbol 'pcs*macro)
- (if error?
- (error "The first argument to MACRO-FUNCTION, ~S, was not a symbol."
- symbol))))
-
- (defun-clcp primop-handler (symbol &optional (error? t))
- (if (symbolp symbol)
- (get symbol 'pcs*primop-handler)
- (if error?
- (error "The first argument to PRIMOP-HANDLER, ~S, was not a symbol."
- symbol))))
-
- (defun-clcp rename-macro (old new)
- (putprop new (get old 'pcs*macro) 'pcs*macro)
- (remprop old 'pcs*macro))
-
- (defun-clcp rename-primop (old new)
- (when (get old 'pcs*primop-handler)
- (putprop new (get old 'pcs*primop-handler) 'pcs*primop-handler)
- (remprop old 'pcs*primop-handler))
- (when (get old 'pcs*opcode)
- (putprop new (get old 'pcs*opcode) 'pcs*opcode)
- (remprop old 'pcs*opcode)))
-
- (define (copy-primop from to)
- (setf (primop-handler to) (primop-handler from)))
-
- ;; Use EVAL to suppress the effect of the alias.
- ;; (Actually, we no longer alias FLOOR, but keep it this way anyway.)
-
- (unless (getprop 'scheme-case 'pcs*macro)
-
- (rename-macro 'let 'scheme-let)
- (rename-macro 'let* 'scheme-let*)
- ;(rename-macro 'cond 'scheme-cond)
- (rename-macro 'case 'scheme-case)
- (rename-macro 'do 'scheme-do)
- (rename-macro 'error 'scheme-error)
-
- (define scheme-floor (eval 'floor))
- (define scheme-ceiling (eval 'ceiling))
- (define scheme-truncate (eval 'truncate))
- (define scheme-round (eval 'round))
- (define scheme-member (eval 'member))
- (define scheme-fresh-line (eval 'fresh-line))
- (define scheme-read (eval 'read))
- (define scheme-write (eval 'write))
-
- (define scheme-apply (eval 'apply))
- (define scheme-assoc (eval 'assoc))
- (define scheme-length (eval 'length))
- (define scheme-read-char (eval 'read-char))
- (define scheme-write-char (eval 'write-char))
- (define scheme-make-string (eval 'make-string))
-
- (rename-primop 'apply 'scheme-apply)
- (rename-primop 'assoc 'scheme-assoc)
- (rename-primop 'length 'scheme-length)
- (rename-primop 'read-char 'scheme-read-char)
- (rename-primop 'write-char 'scheme-write-char)
- (rename-primop 'make-string 'scheme-make-string)
- )
-
- (defun-clcp %%transform-let-bindings (bindings)
- (mapcar (lambda (binding)
- (cond ((symbolp binding)
- (list binding 'nil))
- ((and (consp binding) (null (cdr binding)))
- (list (car binding) 'nil))
- (else
- binding)))
- bindings))
-
- (defmacro let (bindings &body body)
- `(scheme-let ,(%%transform-let-bindings bindings) . ,body))
-
- (defmacro let* (bindings &body body)
- `(scheme-let* ,(%%transform-let-bindings bindings) . ,body))
-
- ;; Change this so that if there is no ELSE clause, add (ELSE NIL).
-
- ; (defmacro cond (&body clauses)
- ; (let ((result ()))
- ; (do ((l clauses (cdr l)))
- ; ((null l))
- ; (let ((clause (car l)))
- ; (cond ((memq (car clause) '(t otherwise))
- ; (unless (null (cdr l))
- ; (error "T or OTHERWISE must be final COND clause"))
- ; (push `(else . ,(cdr clause)) result))
- ; (else
- ; (push clause result)))))
- ; `(scheme-cond . ,(nreverse result))))
-
- ;; Change this so that if there is no ELSE clause, we add (ELSE NIL).
-
- (defmacro case (key &body clauses)
- `(scheme-case ,key .
- ,(let ((final-clause-key nil))
- (map (lambda (clause)
- (when final-clause-key
- (error "A ~A clause in a CASE statement is followed by ~
- the clause ~S"
- final-clause-key clause))
- (cond ((memq (car clause) '(t otherwise))
- (setq final-clause-key (car clause))
- `(else . ,(cdr clause)))
- ((null (cdr clause))
- `(,(car clause) nil))
- (else
- clause)))
- clauses))))
-
- (define-integrable ecase case)
-
- ;; Treat NIL as a special case to minimize consing.
-
- (defun make-return-from (name)
- (if (eq name 'nil)
- 'return-from-nil
- (symbol-append 'return-from- name)))
-
- (defmacro return-from (name &optional value)
- (unless (symbolp name)
- (error "The first argument to RETURN-FROM, ~S, was not a symbol." name))
- `(,(make-return-from name) ,value))
-
- (defmacro return (&optional value)
- `(,(make-return-from 'nil) ,value))
-
- ;; This should MAPFORMS over the body. If RETURN-FROM does not appear within
- ;; the lexical contour defined by the BLOCK, then don't generate CALL/CC.
-
- (defmacro block (name &body body)
- (unless (symbolp name)
- (error "The first argument to BLOCK, ~S, was not a symbol." name))
- `(call/cc (lambda (,(make-return-from name)) . ,body)))
-
- (defmacro do (vars test &body body)
- (unless (cdr test)
- (setq test (list (car test) 'nil)))
- `(block nil (scheme-do ,vars ,test . ,body)))
-
- (defmacro loop (&body body)
- `(block nil (scheme-do () (nil) . ,body)))
-
- (defmacro prog (bindings &body body)
- `(block nil (let ,bindings . ,body)))
-
- ;; Allow the first argument to be a symbol as well as a function.
- ;; Accept additional arguments before the final list argument, i.e.
- ;; ZetaLisp LEXPR-FUNCALL.
-
- (define (apply fcn . args)
- (cond ((procedure? fcn))
- ((symbolp fcn)
- (setq fcn (eval fcn)))
- (else
- (error "The first argument to APPLY, ~S, ~
- is not a procedure or symbol."
- fcn)))
- ;; I'm not sure this is always safe to do.
- ;; We may be clobbering some constant list structure someplace.
- (if (null (cdr args))
- (scheme-apply fcn (car args))
- (progn
- (do ((l args (cdr l)))
- ((null (cddr l))
- (setf (cdr l) (cadr l))))
- (scheme-apply fcn args))))
-
- (defun binary-floor (numerator &optional denominator)
- (if denominator
- ;; Yes, I know there are more efficient ways of doing this.
- (scheme-floor (/ numerator denominator))
- (scheme-floor numerator)))
-
- (defun binary-ceiling (numerator &optional denominator)
- (if denominator
- ;; Yes, I know there are more efficient ways of doing this.
- (scheme-ceiling (/ numerator denominator))
- (scheme-ceiling numerator)))
-
- (defun binary-truncate (numerator &optional denominator)
- (if denominator
- ;; Yes, I know there are more efficient ways of doing this.
- (scheme-truncate (/ numerator denominator))
- (scheme-truncate numerator)))
-
- (defun binary-round (numerator &optional denominator)
- (if denominator
- ;; Yes, I know there are more efficient ways of doing this.
- (scheme-round (/ numerator denominator))
- (scheme-round numerator)))
-
- ;; FLOOR, CEILING, TRUNCATE, and ROUND are integrable.
- ;; Therefore, it is necessary to use DEFINE-INTEGRABLE rather than DEFINE so
- ;; that the original definitions are not integrated into the code.
-
- (define-integrable floor binary-floor)
- (define-integrable ceiling binary-ceiling)
- (define-integrable truncate binary-truncate)
- (define-integrable round binary-round)
-
- (define-integrable rplaca set-car!)
- (define-integrable rplacd set-cdr!)
-
- ;; REVERSE! is not defined in the R^3 standard.
-
- (define-integrable nreverse reverse!)
-
- (define-integrable rest cdr)
- (define-integrable first car)
- (define-integrable second cadr)
- (define-integrable third caddr)
- (define-integrable fourth cadddr)
-
- (defun-inline fifth (x) (car (cddddr x)))
- (defun-inline sixth (x) (cadr (cddddr x)))
- (defun-inline seventh (x) (caddr (cddddr x)))
- (defun-inline eighth (x) (cadddr (cddddr x)))
- (defun-inline ninth (x) (car (cddddr (cddddr x))))
- (defun-inline tenth (x) (cadr (cddddr (cddddr x))))
-
- (define-integrable char-code char->integer)
- (define-integrable code-char integer->char)
-
- (define-integrable char string-ref)
- (define-integrable schar string-ref)
- (define-integrable svref vector-ref)
-
- ;; Arrays
-
- (defun arrayp (x)
- (or (stringp x) (vectorp x)))
-
- (defun aref (array subscript)
- (cond ((stringp array)
- (string-ref array subscript))
- ((vectorp array)
- (vector-ref array subscript))
- (else
- (error "The first argument to AREF, ~S, is not an array."
- array))))
-
- (defun-clcp %%setf-aref (value array subscript)
- (cond ((stringp array)
- (string-set! array subscript value))
- ((vectorp array)
- (vector-set! array subscript value))
- (else
- (error "The second argument to SETF-AREF, ~S, is not an array."
- array)))
- value)
-
- (define-integrable make-array make-vector)
-
- ;; Strings (p. 300-302)
-
- (defun string (x)
- (cond ((stringp x)
- x)
- ((symbolp x)
- (symbol-name x))
- ((characterp x)
- (make-string 1 :initial-element x))
- (else
- (error "The argument, ~S, cannot be coerced to a string." x))))
-
- ;; The following functions can be compiled inline if the arguments are
- ;; declared to be simple strings.
-
- (defun string= (string1 string2)
- (string=? (string string1) (string string2)))
-
- (defun string-equal (string1 string2)
- (string-ci=? (string string1) (string string2)))
-
- (defun string< (string1 string2)
- (string<? (string string1) (string string2)))
-
- (defun string> (string1 string2)
- (string>? (string string1) (string string2)))
-
- (defun string<= (string1 string2)
- (string<=? (string string1) (string string2)))
-
- (defun string>= (string1 string2)
- (string>=? (string string1) (string string2)))
-
- (defun string/= (string1 string2)
- (not (string=? (string string1) (string string2))))
-
- (defun string-lessp (string1 string2)
- (string-ci<? (string string1) (string string2)))
-
- (defun string-greaterp (string1 string2)
- (string-ci>? (string string1) (string string2)))
-
- (defun string-not-greaterp (string1 string2)
- (string-ci<=? (string string1) (string string2)))
-
- (defun string-not-lessp (string1 string2)
- (string-ci>=? (string string1) (string string2)))
-
- (defun string-not-equal (string1 string2)
- (not (string-ci=? (string string1) (string string2))))
-
- ;; p. 303
-
- (defun-clcp %%string-case (string1 char-case)
- (setq string1 (string string1))
- (let* ((length (length string1))
- (string2 (make-string length)))
- (dotimes (i length)
- (setf (char string2 i) (char-case (char string1 i))))
- string2))
-
- (defun string-upcase (string)
- (%%string-case string char-upcase))
-
- (defun string-downcase (string)
- (%%string-case string char-downcase))
-
- ;; We can only get one value back, so bind the rest to NIL and hope they
- ;; aren't important. Later, implement this in terms of CALL/CC if possible.
-
- (defmacro multiple-value-bind (variables form &body body)
- (unless (pair? variables)
- (error "The first argument to MULTIPLE-VALUE-BIND, ~S, is not a ~
- list of variables."
- variables))
- (unless (pair? form)
- (error "The second argument to MULTIPLE-VALUE-BIND, ~S, is not a ~
- form to evaluate."
- form))
- `(let ((,(car variables) ,form) .
- ,(map (lambda (variable) `(,variable nil)) (cdr variables)))
- . ,body))
-
- ;; Packages (snicker!)
-
- (defvar *package*)
-
- (defun in-package (package-name)
- (setq *package* package-name))
-
- (defun export (symbols &optional package))
-
- ;; Modules
-
- (defvar *modules* nil)
-
- (defun provide (module)
- (unless (member module *modules*)
- (push module *modules*)))
-
- (defun require (module &optional pathname)
- (unless (member module *modules*)
- (if pathname
- (load pathname)
- (error "The module ~A has not been provided." module))))
-
- (defun lisp-implementation-type ()
- "PC Scheme Common Lisp Compatibility Package")
-
- (defun lisp-implementation-version () "1.09")
-
- (defun machine-type () "IBM PC compatible")
- (defun machine-version () nil)
- (defun machine-instance () nil)
- (defun software-type () "PC-DOS")
- (defun software-version () nil)
-
- (defvar *features* '(ieee-floating-point))
-
- (defun identity (x) x)
-
- (defmacro boundp (thing)
- (unless (and (listp thing)
- (null (cddr thing))
- (eq (car thing) 'quote)
- (symbolp (cadr thing)))
- (error "Unable to translate BOUNDP of ~S." thing))
- `(fluid-bound? ,(cadr thing)))
-
- (defmacro eval-when (situation &body body)
- `(begin . ,body))
-
- ;; This used to be (defmacro function (x) x) but that made it impossible to
- ;; use the FUNCTION as a variable. Yet another reason this package should be
- ;; rewritten as a translator. FUNCTION is a special form, not a function, so
- ;; the following definition isn't quite correct. However, since FUNCTION is
- ;; often used as a variable, this is the best compromise for now.
-
- (defun-inline function (x) x)
-
- (defun-clcp %%defstruct-initial-slots (initial-slots)
- (let ((result ()))
- (do ((l initial-slots (cddr l)))
- ((null l))
- (when (null (cdr l))
- (error "The keyword ~S does not have a matching value ~
- in a DEFSTRUCT constructor."
- (car l)))
- (let ((keyword (car l)))
- (when (and (listp keyword)
- (= (length keyword) 2)
- (eq (car keyword) 'quote))
- (setq keyword (cadr keyword)))
- (when (symbolp keyword)
- (let ((name (symbol-name keyword)))
- (when (char= (char name 0) #\:)
- (setq keyword (list 'quote (intern (subseq name 1)))))))
- (push keyword result)
- (push (cadr l) result)))
- (nreverse result)))
-
- ;; Checking for a PRIMOP-HANDLER is needed here when using LOAD.
-
- (defun-clcp %%defstruct-synonym (old-name new-name)
- `(unless (primop-handler ',new-name)
- (define ,new-name ,old-name)
- (copy-primop ',old-name ',new-name)))
-
- (defun-clcp %%defstruct (name slots include conc-name print-function)
- (let ((defstruct-slots
- (if include (reverse (get include 'defstruct-slots)) ()))
- (constructor (symbol-append 'make- name))
- (internal-constructor (symbol-append '%%defstruct-make- name)))
- (dolist (slot slots)
- (push (if (symbolp slot) slot (car slot)) defstruct-slots))
- (setq defstruct-slots (nreverse defstruct-slots))
- (let ((result
- `((define-structure
- ,(if include
- `(,name (include ,include))
- name)
- . ,slots)
- (putprop ',name ',defstruct-slots 'defstruct-slots)
- (define ,internal-constructor ,constructor)
- (defmacro ,constructor (&rest initial-slots)
- (cons ',internal-constructor
- (%%defstruct-initial-slots initial-slots)))
- )))
- (when conc-name
- (let ((synonyms ()))
- (dolist (slot defstruct-slots)
- (let ((old-name (symbol-append name "-" slot))
- (new-name (symbol-append conc-name slot)))
- ;; Checking for a PRIMOP-HANDLER is needed here when using
- ;; COMPILE.
- (unless (primop-handler new-name)
- (push (%%defstruct-synonym old-name new-name)
- synonyms))))
- (setq result (append result synonyms))))
- (cons 'begin
- (nconc result
- (if print-function
- (list `(putprop ',name
- ',print-function
- 'print-function)))
- (list `',name))))))
-
- (defmacro defstruct (description &rest slots)
- (let ((name description)
- (include nil)
- (conc-name nil)
- (print-function nil))
- (cond ((symbolp description))
- ((not (listp description))
- (error "The first argument to DEFSTRUCT, ~S, was not a ~
- symbol or list."
- description))
- (else
- (setq name (pop description))
- (for-each
- (lambda (clause)
- (let ((key (first clause))
- (value (second clause)))
- (case key
- (:include
- (setq include value))
- (:conc-name
- (setq conc-name value))
- (:print-function
- (setq print-function value))
- (else
- (error "The DEFSTRUCT argument ~S is unrecognized."
- clause)))))
- description)))
- ;; Discard documentation string if one exists.
- (when (stringp (car slots))
- (pop slots))
- (%%defstruct name slots include conc-name print-function)))
-
- ;; Returns #F or the structure symbol.
-
- (defun-clcp %%structurep (x)
- (and (vectorp x)
- (consp (setq x (svref x 0)))
- (consp (setq x (car x)))
- (eq (car x) '#!STRUCTURE)
- (cdr x)))
-
- ;; (defun typep (thing type)
- ;; (and (%%structurep thing)
- ;; (eq (cdar (svref thing 0)) type)))
-
- (defun typep (thing type)
- (and (vectorp thing)
- (symbolp type)
- (eq (svref thing 0) (get type '%tag))))
-
- ;; Pathnames and directories
-
- (define-integrable directory dos-dir)
- (define-integrable namestring identity)
-
- (defun truename (thing)
- (cond ((output-port? thing)
- "#<Output Port>")
- ((input-port? thing)
- "#<Input Port>")
- (else
- thing)))
-
- (defun pathnamep (thing) nil)
-
- (defun probe-file (file)
- (let ((dir (dos-dir file)))
- (if dir (car dir))))
-
- (newline)
- (writeln " Common Lisp Compatibility Package "
- (lisp-implementation-version)
- " 9 September 1990")
- (writeln "(C) Copyright 1990 by Carl W. Hoffman")
- (writeln " All Rights Reserved.")